from symbide import PATHS
from symbide.src.parsing import parsers
from symbide.src.widgets import WAIT_ANIMATION
from image import Image 

from gobject import idle_add
import gtk
from threading import Thread
from os import listdir, remove
import os.path
from time import sleep, time
from xml.dom import minidom
from symbide.src.utils import createUniquePath

#TODO: implement undo functionality for plots

class SympyplotWidget(Image):
    '''
    This widget capsulates a sympy.Plot-object and so enables
    plotting functionality.
    '''
    
    def __init__(self, DOM):
        
        Image.__init__(self, show=False)
        
        self.path = createUniquePath(PATHS['temp_pictures'], 'sympyplot')
        self.DOM = DOM
        self.changed = False
        self.plot = None #here is the sympy.Plot object stored
        
        #produce a first screenshot without opening the interactive window.
        
        self.image.set_from_animation(WAIT_ANIMATION)
        
        self.Thread = Thread(target=self.screenshot)
        self.Thread.setDaemon(True)
        self.Thread.setName('SympyplotScreenshotCalculation')
        self.Thread.start()
        
    def _event_mouseEnter(self, widget, event):
        '''
        Changes the curser to a circled arrow when it enters.
        '''
        
        gtk.gdk.Window.set_cursor(self.window, gtk.gdk.Cursor(gtk.gdk.EXCHANGE))
        
    def _event_mouseLeave(self, widget, event):
        '''
        Changes the cursor back to normal when it leaves.
        '''
        
        cursor = gtk.gdk.ARROW
        gtk.gdk.Window.set_cursor(self.window, gtk.gdk.Cursor(gtk.gdk.ARROW))            
        
    def _event_leftMouseClick(self, widget, event):
        '''
        Opens the intaractive plotting window when the widget is doubleclicked.
        '''
        
        assert self.path
        if event.type!=gtk.gdk._2BUTTON_PRESS:
            return
        
        self.changed = True
        
        #create a new plot-object if necessary and start session    
        if not self.plot or self.plot._window.has_exit:
            self.plot = parsers['plot'].dom_to_plot(self.DOM)
            thread = Thread(target=self._updateLoop)
            thread.setDaemon(True)
            thread.setName('Sympyplot3dWindow')
            thread.start()
        else:
            self.plot._window.set_visible(True)
            
    def _updateLoop(self):
        '''
        Updates the widget in a certain interval, as long as the
        interactive window is opened. Afterwards it gets the new
        DOM reapresentation of the plot-object.
        '''
        
        assert self.path
        interval = 2
        last = 0
        while not self.plot._window.has_exit:
            t = time()
            if t-last>interval:
                last = t
                self.plot.saveimage(self.path)
                self.showImage()
            sleep(0.6)
        self.showImage()
        self.DOM = parsers['plot'].plot_to_dom(self.plot)
    
    def screenshot(self):
        '''
        Creates a screenshot without opening the interactive window.
        '''
        
        assert self.path
        #create a new plot object if necessary
        if not self.plot or self.plot._window.has_exit:
            self.plot = parsers['plot'].dom_to_plot(self.DOM, interactive=False)
            
        self.plot.saveimage(self.path)
        
        #now wait until image is saved
        self.plot._window.Thread.join()
        self.showImage()

            
    def todom(self):
        '''
        Returns a DOM representation of the plot-object.
        '''
        
        assert self.path
        self.DOM.setAttribute('path',self.path)
        return self.DOM
    
    def toxml(self):
        '''
        Returns a xml representation of the plot-object.
        '''
        
        return self.todom().toxml()
    
    def showImage(self):
        '''
        Gives the main-thread the command to show the image.
        '''
        
        idle_add(Image.showImage, self)
    
    def destroy(self):
        '''
        Cleans up everything.
        '''
        
        try:
            gtk.EventBox.destroy(self)
            if self.plot and not self.plot._window.has_exit:
                self.plot.close()
                del self.plot
            if self.path and isinstance(self.path, str) and os.path.exists(self.path):
                remove(self.path)
            self.DOM.unlink()
            del self.DOM
            del self.path
        except:
            pass